package com.shuimin.group.service;

import com.shuimin.group.App;
import com.shuimin.group.constant.GroupLifeCycle;
import com.shuimin.group.constant.GroupStatus;
import com.shuimin.group.logic.GroupLogic;
import com.shuimin.group.logic.LocationLogic;
import com.shuimin.group.mid.redis.RedisKey;
import com.shuimin.group.mid.redis.RedisService;
import com.shuimin.group.mid.redis.RedisUtil;
import com.shuimin.group.model.group.GroupInMem;
import com.shuimin.group.model.group.GroupType;
import com.shuimin.group.model.group.VGroup;
import com.shuimin.group.model.group.VGroupMember;
import com.shuimin.group.model.place.Place;
import pond.common.S;
import pond.common.STRING;
import pond.common.f.Tuple;
import pond.db.sql.Criterion;
import pond.db.sql.Sql;
import pond.db.sql.SqlSelect;

import java.util.*;

public class GroupService {
    public static final String GROUP_QUERY_KEY_ISJOIN = "isJoin";
    public static final String GROUP_QUERY_KEY_ISCREATOR = "isCreator";
    public static final String GROUP_QUERY_KEY_GROUP_TYPE = "group_type";
    public static final String GROUP_QUERY_KEY_GPS_DISTANSE = "gps";
    public static List<GroupType> allGroupType() {
        return App.DB.get(t -> t.query(GroupType.class,"select * from t_group_type;"));
    }

    public static List<VGroup> createAllVGroup(){
        SqlSelect sql = Sql.select("*").from("v_group");
        String[] activeList = new String[]{
                GroupStatus.GROUP_STATUS_CREATE.val(),
        };
        List <VGroup> list  = App.DB.get(t-> t.query(VGroup.class, sql.where("group_status", Criterion.IN, activeList)));
        if (list == null || list.size() ==0)
        {
            return new ArrayList<>();
        }
        else {
            return list;
        }
    }
    /*  GroupInMem vGroupMemberList 不能存在重复成员*/
    public static boolean isJoin(String userId, List<Map<String, Object>> memberList){
        if (null == userId || null == memberList  ||  0 == memberList.size())
            return false;
        for (int i =0; i< memberList.size(); i++)
        {
            Map<String,Object> map = memberList.get(i);
            S.echo("isok:"+map.get("user_id")+"="+userId);
            if (map.get("user_id").equals(userId))
            {
                return true;
            }
        }
        return false;
    }

    public static boolean isCreator(String userId, VGroup vGroup ){
        if ( null == userId || null == vGroup || null == vGroup.user())
            return false;
        return userId.equals(vGroup.user().id().toString());
    }
    public static boolean isOk(String userId, VGroup vGroup, List<Map<String, Object>> memberList, Map<String,Object> params)
    {
        if (null == params)
        {
            return true;
        }
        S._assertNotNull(vGroup);
        final boolean[] ret = {true};

        S._for(params).each(
            param->{
                if (param.getKey().equals(GROUP_QUERY_KEY_ISJOIN))
                {
                    if (!isJoin(userId,memberList))
                    {
                        ret[0] = false;
                        return;
                    }
                }
                if (param.getKey().equals(GROUP_QUERY_KEY_ISCREATOR))
                {
                    if (!isCreator(userId,vGroup))
                    {
                        ret[0] = false;
                        return;
                    }
                }
                if (param.getKey().equals(GROUP_QUERY_KEY_GROUP_TYPE))
                {
                    List<String> list = Arrays.asList((String[])param.getValue()) ;
                    String group_type_id= vGroup.get("group_type_id");
                    if (! list.contains(group_type_id))
                    {
                        ret[0] = false;
                        return;
                    }
                }
                if (param.getKey().equals(GROUP_QUERY_KEY_GPS_DISTANSE))
                {
                    //todo 可以优化
                    Tuple.T3<Double,Double,Double> gps = (Tuple.T3<Double,Double,Double>) param.getValue();
                    double[] gps_ranges = LocationLogic.squarePoint(gps._a,gps._b,gps._c);
                    Place place = vGroup.place();
                    double gps_x = Double.valueOf(place.get("gps_x")).doubleValue();
                    double gps_y = Double.valueOf(place.get("gps_y")).doubleValue();
                    if (gps_x < gps_ranges[0] || gps_x > gps_ranges[1] || gps_y < gps_ranges[2] || gps_y > gps_ranges[3] )
                    {
                        ret[0] = false;
                        return;
                    }
                }
            }
        );

        return ret[0];
    }
    public static Map<String,Object> getGroupMember(String userId, List<Map<String, Object>> memberList)
    {
        S._assertNotNull(userId,memberList);
        Map<String,Object> map = new HashMap<>();
        S._for(memberList).each(member ->{
            if (userId.equals(member.get("user_id")))
            {
                map.putAll(member);
            }
        });
        return  map;
    }
    /* group 一级查询
    *  1. create:*   2. create:place_id:*
    *  state:place_id:time:group_id (group_type 放在二级查询)
    */

    public static Map<String, Object> transfer(String userId, VGroup vGroup, List<Map<String, Object>> memberList, Map<String,Object> params)
    {
        Map<String, Object> map = new HashMap<>();
        S.echo("vGroup:"+vGroup);
        map.putAll(vGroup.group().toMap());
        map.put("place",   PlaceService.mapObjFromVGroup(vGroup));
        map.put("creator", vGroup.user());
        map.put("members", memberList);
        map.put("member_num",memberList.size());
        if (STRING.notBlank(userId)) {
            map.put("is_creator", isCreator(userId, vGroup));
            Map<String, Object> groupMemberMap = getGroupMember(userId, memberList);
            if (groupMemberMap != null && groupMemberMap.size() > 0) {
                map.put("is_join", true);
                map.put("join_time", groupMemberMap.get("op_time"));
            } else {
                map.put("is_join", false);
            }
        }
        if (params.containsKey(GROUP_QUERY_KEY_GPS_DISTANSE))
        {
            Tuple.T3<Double,Double,Double> gps = (Tuple.T3<Double,Double,Double>) params.get(GROUP_QUERY_KEY_GPS_DISTANSE);
            Place place = vGroup.place();
            double gps_x = Double.valueOf(place.get("gps_x")).doubleValue();
            double gps_y = Double.valueOf(place.get("gps_y")).doubleValue();
            map.put("distance", LocationLogic.figuredMiles(gps_x,gps_y,gps._a,gps._b));
        }
        return map;
    }
    public static Map<String, Object> sys_transfer(VGroup vGroup, List<Map<String, Object>> memberList)
    {
        Map<String, Object> map = new HashMap<>();
        S.echo("vGroup:"+vGroup);
        map.putAll(vGroup.group().toMap());
        map.put("place",   PlaceService.mapObjFromVGroup(vGroup));
        map.put("creator", vGroup.user());
        map.put("members", memberList);
        map.put("member_num",memberList.size());
        return map;
    }
    public static List<Map<String, Object>> allGroup(String userId, Map<String,Object> params)
    {
        List<String> keyList = RedisService.getKeysFromParams(params);
        List<Map<String, Object>> retList = new ArrayList<>();
        if (null == keyList || keyList.size() == 0)
        {
            return retList;
        }
        List<Map<String,Object>> vgroupList = RedisUtil.hscanObjectFromKeys(keyList);

        S._for(vgroupList).each( vgroupMap->{
            Map<String, Object> map = new HashMap<>();
            VGroup vGroup = new VGroup();
            S.echo("map:"+vgroupMap);
            vGroup.merge(vgroupMap);
            //group_id:user_id:member
            List<String> memberKeyList = RedisUtil.keys(vGroup.id()+"*"+RedisKey.MEMBER);
            List<Map<String, Object>> memberList = RedisUtil.hscanObjectFromKeys(memberKeyList);
            if (isOk(userId, vGroup, memberList, params)) {
                retList.add(transfer(userId, vGroup, memberList, params));
            }

        });
        return retList;
    }
    public static Map<String, Object> getGroupById(String id)
    {
        S._assertNotNull(id);
        String key = RedisService.getGroupKeyById(id);
        if (STRING.isBlank(key))
        {
            return  new HashMap<>();
        }
        else
        {
            Map<String,Object> vgroupMap = RedisUtil.hscanObjectsFromKey(key);
            VGroup vGroup = new VGroup();
            S.echo("map:"+vgroupMap);
            vGroup.merge(vgroupMap);
            //group_id:user_id:member
            List<String> memberKeyList = RedisUtil.keys(vGroup.id()+"*"+RedisKey.MEMBER);
            List<Map<String, Object>> memberList = RedisUtil.hscanObjectFromKeys(memberKeyList);
            return sys_transfer(vGroup, memberList);
        }
    }
    public static GroupLifeCycle next(GroupLifeCycle groupLifeCycle)
    {
        switch (groupLifeCycle)
        {
            case notify_delay: groupLifeCycle = GroupLifeCycle.join_end; break;
            case join_end:groupLifeCycle =  GroupLifeCycle.send_sign;break;
            case send_sign:groupLifeCycle = GroupLifeCycle.calc_sign;break;
            case calc_sign:groupLifeCycle = GroupLifeCycle.send_feedback;break;
            case send_feedback: groupLifeCycle = GroupLifeCycle.game_over;break;
            case game_over: break;
        }
        return groupLifeCycle;
    }

}
